#include <unistd.h>
#include <vector>
#include <iostream>
#include <string>
#include <functional>
#include <pthread.h>
#include "Thread.hpp"
#include "LockGuard.hpp"

const std::string GetName()
{
    static int x = 1;
    char buffer[64];
    snprintf(buffer, sizeof(buffer), "%s-%d", "Thread", x);
    x++;
    return buffer;
}

void Print(int num)
{
    while (num)
    {
        std::cout << "hello OS " << num-- << std::endl;
        sleep(1);
    }
}

int ticket = 1000;
// pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

class ThreadData
{
public:
    ThreadData(const std::string& threadname,  pthread_mutex_t *mutex)
        :_mutex(mutex), _threadname(threadname)
    {}
    ~ThreadData()
    {}
public:
    pthread_mutex_t *_mutex;
    const std::string& _threadname;
};

void GetTicket(ThreadData* td)
{
    while (ticket)
    {
        // pthread_mutex_lock(mutex);
        {
            LockGuard lg(td->_mutex);
            if (ticket > 0)
            {
                usleep(1000); // 充当抢票时间
                printf("%s, get ticket: %d\n", td->_threadname.c_str(), ticket);
                // printf("get ticket: %d\n", ticket);
                ticket--;
                // pthread_mutex_unlock(mutex);
            }
            else
            {
                // pthread_mutex_unlock(mutex);
                break;
            }
        }
    }
}

int main()
{
    pthread_mutex_t mutex;
    pthread_mutex_init(&mutex, nullptr);

    const std::string name1 = GetName();
    ThreadData td1(name1, &mutex);
    Thread<ThreadData*> t1(name1, GetTicket, &td1);

    const std::string name2 = GetName();
    ThreadData td2(name2, &mutex);
    Thread<ThreadData*> t2(name2, GetTicket, &td2);

    const std::string name3 = GetName();
    ThreadData td3(name2, &mutex);
    Thread<ThreadData*> t3(name3, GetTicket, &td3);

    const std::string name4 = GetName();
    ThreadData td4(name1, &mutex);
    Thread<ThreadData*> t4(name4, GetTicket, &td4);
    t1.Start();
    t2.Start();
    t3.Start();
    t4.Start();

    t1.Join();
    t2.Join();
    t3.Join();
    t4.Join();

    pthread_mutex_destroy(&mutex);

    // int num = 4;
    // std::vector<Thread<const std::string>> v;
    // for(int i = 0; i < num; i++)
    // {
    //     const std::string name = GetName();
    //     std::cout << name << std::endl;
    //     Thread<const std::string> t(name, GetTicket, name);
    //     v.push_back(t);
    // }
    // for(int i = 0; i < num; i++)
    //     v[i].Start();
    // for(int i = 0; i < num; i++)
    //     v[i].Join();
    return 0;
}